﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using KamLib;

namespace Ext.Net.UIS
{

    public class TermTitle
    {

        #region Constructors

        public TermTitle() { }

        public TermTitle(string middle, object ns = null)
        {
            Middle = middle;
            this.ns = ns;
        }

        public TermTitle(string middle, params string[] ns)
        {
            Middle = middle;
            this.ns = ns;
        }

        #endregion


        #region Titles

        #region Basic

        public string Name { get { return Middle; } set { Middle = value; } }
        public string Names { get { return Middles; } set { Middles = value; } }

        public string Prefix { get { return MiddlePrefix; } set { MiddlePrefix = value; } }
        public string Prefixes { get { return MiddlePrefixes; } set { MiddlePrefixes = value; } }

        public string Postfix { get { return MiddlePostfix; } set { MiddlePostfix = value; } }
        public string Postfixes { get { return MiddlePostfixes; } set { MiddlePostfixes = value; } }

        public string Empty { get; set; }

        #endregion

        #region Long

        private string _Long;
        public string Long
        {
            get { return _Long ?? _Middle ?? _Short; }
            set
            {
                _Long = value;
                if (value == null) return;
                var ss = value.Split('|');
                if (ss.Length >= 1) _Long = ss[0];
                if (ss.Length >= 2) LongPrefix = ss[1];
                if (ss.Length >= 3) LongPostfix = ss[2];
            }
        }
        public string LongPrefix { get; set; }
        public string LongPostfix { get; set; }

        private string _Longs;
        public string Longs
        {
            get { return _Longs ?? _Middles ?? _Shorts ?? Long; }
            set
            {
                _Longs = value;
                if (value == null) return;
                var ss = value.Split('|');
                if (ss.Length >= 1) _Longs = ss[0];
                if (ss.Length >= 2) LongPrefixes = ss[1];
                if (ss.Length >= 3) LongPostfixes = ss[2];
            }
        }
        public string LongPrefixes { get; set; }
        public string LongPostfixes { get; set; }

        #endregion


        #region Middle

        private string _Middle;
        public string Middle
        {
            get { return _Middle ?? _Long ?? _Short; }
            set
            {
                _Middle = value;
                if (value == null) return;
                var ss = value.Split('|');
                if (ss.Length >= 1) _Middle = ss[0];
                if (ss.Length >= 2) MiddlePrefix = ss[1];
                if (ss.Length >= 3) MiddlePostfix = ss[2];
            }
        }
        public string MiddlePrefix { get; set; }
        public string MiddlePostfix { get; set; }

        private string _Middles;
        public string Middles
        {
            get { return _Middles ?? _Longs ?? _Shorts ?? Middle; }
            set
            {
                _Middles = value;
                if (value == null) return;
                var ss = value.Split('|');
                if (ss.Length >= 1) _Middles = ss[0];
                if (ss.Length >= 2) MiddlePrefixes = ss[1];
                if (ss.Length >= 3) MiddlePostfixes = ss[2];
            }
        }
        public string MiddlePrefixes { get; set; }
        public string MiddlePostfixes { get; set; }

        #endregion


        #region Short

        private string _Short;
        public string Short
        {
            get { return _Short ?? _Middle ?? _Long; }
            set
            {
                _Short = value;
                if (value == null) return;
                var ss = value.Split('|');
                if (ss.Length >= 1) _Short = ss[0];
                if (ss.Length >= 2) ShortPrefix = ss[1];
                if (ss.Length >= 3) ShortPostfix = ss[2];
            }
        }
        public string ShortPrefix { get; set; }
        public string ShortPostfix { get; set; }

        private string _Shorts;
        public string Shorts
        {
            get { return _Shorts ?? _Middles ?? _Longs ?? Short; }
            set
            {
                _Shorts = value;
                if (value == null) return;
                var ss = value.Split('|');
                if (ss.Length >= 1) _Shorts = ss[0];
                if (ss.Length >= 2) ShortPrefixes = ss[1];
                if (ss.Length >= 3) ShortPostfixes = ss[2];
            }
        }
        public string ShortPrefixes { get; set; }
        public string ShortPostfixes { get; set; }

        #endregion

        #endregion


        public static implicit operator TermTitle(string value)
        {
            return new TermTitle { Middle = value };
        }

        public static implicit operator string(TermTitle value)
        {
            return value != null ? value.Middle : null;
        }


        #region Namespaces

        public readonly Dictionary<string, TermTitle> Namespaces = new Dictionary<string, TermTitle>();

        public object ns { get;  set; }

        public void PrepareNamespaces(Term term)
        {
            if (NamespacesPrepared) return;
            AddNamespaces(term, ns);
            NamespacesPrepared = true;
        }

        private bool NamespacesPrepared;

        public void AddNamespaces(Term term, object o)
        {
            if (o == null) return;


            if (o is Dictionary<string, TermTitle>)
            {
                Namespaces.AddRange((Dictionary<string, TermTitle>)o, true);
            }
            else if (o is string[])
            {
                var p = term.Parent;
                foreach (var s in (string[])o)
                {
                    if (p == null) return;
                    while (p != null && (p.IsAnonymous || p.Name.no()))
                    {
                        p = p.Parent;
                    }
                    if (p == null) return;
                    Namespaces[p.Name] = s;
                    p = p.Parent;
                }
            }
            else
            {
                foreach (var prop in o.GetType().GetPropertiesAndFields())
                {
                    var value = prop.GetValue(o, null);
                    var title =
                        value is TermTitle
                            ? (TermTitle)value
                            : value is string
                                ? (TermTitle)(string)value
                                : null;
                    if (title != null)
                        Namespaces[prop.Name] = title;
                }
            }
        }

        #endregion


        #region Utils

        public override string ToString() { return Middle; }

        #endregion


    }


    public static class FieldTitleHelper
    {
        public static bool yes(this TermTitle title) { return title != null && title.Middle.yes(); }
        public static bool no(this TermTitle title) { return title == null || title.Middle.no(); }
    }

}
